package com.alibaba.moco.gitlab;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.moco.monitor.ScriptClassLoader;
import com.alibaba.moco.util.BaseTypeUtil;

import groovy.util.ResourceException;
import groovy.util.ScriptException;

/**
 * Gitlab脚本加载处理类
 * @author wb-lj240895
 *
 */
public class GitlabGroovyLoader {
	
	private static final String RESOURCE_LIST_FILE_NAME = "resource.list";
	private static final String RESOURCE_SCRIPT = "resources/script";
	private static final String VERSION_INFO_FILE = "version.info";
	private static final String GROOVY_SUFFIX = ".groovy";
	
	private static final Logger logger = LoggerFactory.getLogger(GitlabGroovyLoader.class);
	
	
	/**
	 * 脚本初始化
	 * @throws ScriptException 
	 * @throws ResourceException 
	 * @throws IOException 
	 * @throws InstantiationException 
	 * @throws IllegalAccessException 
	 */
	public static void init() throws Exception{
		logger.info("gitlab groovy 脚本初始化....");
		logger.info("获取Gitlab 资源列表文件 filename：" , RESOURCE_LIST_FILE_NAME);
		GitlabFileResVo source = GitlabApiUtil.getFileContent(RESOURCE_LIST_FILE_NAME);
		
		if (source != null) {
			String content = source.getContent();
			content = content.replace("\n", "");
			String scriptPath = ScriptClassLoader.getScriptPath();
			String[] fileNames = content.split(";");
			List<File> scriptFile = new ArrayList<File>();
			for (String fileName :fileNames){
				GitlabFileResVo scriptSource = GitlabApiUtil.getFileContent(RESOURCE_SCRIPT + fileName);
				if (scriptSource != null){
					String script = scriptSource.getContent();
					
					File file = saveToFile(scriptPath + fileName, script);
					if (file != null && file.exists()){
						scriptFile.add(file);
					}else{
						logger.warn("脚本文件未保存成功？脚本无法加载？ ：{}",scriptPath + fileName);
					}
				}else{
					logger.info("gitlab 不存在脚本：scriptName:{}",fileName);
				}
			}
			//解决加载时找不到类的问题
			for(File file : scriptFile){
				ScriptClassLoader.loadScriptClass(file);
			}
		}else{
			logger.error("获取脚本清单失败  请检查 Gitlab中的清单文件{}",RESOURCE_LIST_FILE_NAME);
		}
	}
	/**
	 * 检查更新
	 * @return
	 * @throws ScriptException 
	 * @throws ResourceException 
	 * @throws IOException 
	 * @throws InstantiationException 
	 * @throws IllegalAccessException 
	 */
	public static void checkUpdate() throws Exception{
		//获取最新版本ID
		GitlabBranchResVo gitlabBranchResVo = GitlabApiUtil.getBranchInfo();
		if (gitlabBranchResVo != null) {
			String gitlabVersionId = gitlabBranchResVo.getCommit().getId();
			//获取本地资源版本信息
			String localVersionId = readLocalFile(BaseTypeUtil.getClassPath() + VERSION_INFO_FILE);
			if (StringUtils.isBlank(localVersionId)){
				//本地不存在版本信息时更新全部脚本并创建版本信息
				init();
				saveToFile(BaseTypeUtil.getClassPath() + VERSION_INFO_FILE, gitlabVersionId);
			}else{ //比较版本信息 若相同则不更新
				if (localVersionId.equals(gitlabVersionId)) {
					return;
				} else { //始终保持与gitlab上资源一致
					//检查更新内容
					logger.info("检查到更新  正在更新脚本");
					List<GItlabBranchDiffResVo> diffs = GitlabApiUtil.getCommitDiff(gitlabVersionId);
					if (diffs != null && !diffs.isEmpty()){
						for (GItlabBranchDiffResVo diff: diffs){
							String path = diff.getNew_path();
							
							if (!StringUtils.isBlank(path) && path.endsWith(GROOVY_SUFFIX)){
								GitlabFileResVo gitlabFileResVo = GitlabApiUtil.getFileContent(path);
								if (path.startsWith("resources/")) path = path.replace("resources/", "");
								if (gitlabFileResVo != null){
									String content = gitlabFileResVo.getContent();
									File file = saveToFile(BaseTypeUtil.getClassPath() + path, content);
									if (file.exists()){
										ScriptClassLoader.loadScriptClass(file);
									}
								}
							}
							saveToFile(BaseTypeUtil.getClassPath() + VERSION_INFO_FILE, gitlabVersionId);
						}
					}
				}
			}
		}
		return;
	}

	/**
	 * 文件写入
	 * @param absName
	 * @param content
	 */
	private static File saveToFile(String absName, String content){
		int sep = absName.lastIndexOf("/");
		if (sep != -1){
			//创建文件路径
			String path = absName.substring(0, sep);
			//String name = absName.substring(sep);
			File pathFile = new File(path);
			if(!pathFile.exists()){
				pathFile.mkdirs();
			}
		}
		File file = new File(absName);
		logger.info("文件已写入到{}",absName);
		try {
			BufferedWriter writer = new BufferedWriter(new FileWriter(file));
			writer.write(content);writer.flush();writer.close();
			return file;
		} catch (IOException e) {
			logger.error("文件写入失败, absFileName:{}", absName, e);
			return null;
		}
	}
	/**
	 * 读取本地文件内容
	 * @param absName
	 * @return
	 */
	private static String readLocalFile(String absName){
		try {
			BufferedReader reader = new BufferedReader(new FileReader(absName));
			String temp = reader.readLine();
			StringBuilder builder = new StringBuilder();
			while (temp != null){
				builder.append(temp);
				temp = reader.readLine();
			}
			reader.close();
			return builder.toString();
		} catch (Exception e) {
			logger.error("文件读取失败, absFileName:{}", absName, e);
		}
		return null;
	}
}
